package com.hhkj.admin.sale.service.biz.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hhkj.admin.common.event.EveryTenMinutesEvent;
import com.hhkj.admin.common.util.BaseEntityUtil;
import com.hhkj.admin.conf.common.cont.ConfConst;
import com.hhkj.admin.conf.model.extend.CommissionRate;
import com.hhkj.admin.conf.model.res.CommissionRateRes;
import com.hhkj.admin.conf.service.biz.ConfBizService;
import com.hhkj.admin.order.common.cont.OrderRefundConst;
import com.hhkj.admin.order.domain.Order;
import com.hhkj.admin.order.event.OrderPaySuccessEvent;
import com.hhkj.admin.order.event.RefundPayoutSuccessEvent;
import com.hhkj.admin.sale.common.cont.SaleCommissionConst;
import com.hhkj.admin.sale.common.cont.SaleConst;
import com.hhkj.admin.sale.domain.Sale;
import com.hhkj.admin.sale.domain.SaleCommission;
import com.hhkj.admin.sale.model.dopo.SaleCommissionDo;
import com.hhkj.admin.sale.model.dopo.SaleCommissionPo;
import com.hhkj.admin.sale.model.req.SaleCommissionReq;
import com.hhkj.admin.sale.model.res.SaleCommissionRes;
import com.hhkj.admin.sale.service.base.SaleAccountService;
import com.hhkj.admin.sale.service.base.SaleCommissionService;
import com.hhkj.admin.sale.service.base.SaleService;
import com.hhkj.admin.sale.service.biz.SaleCommissionBizService;
import com.hhkj.admin.sale.service.extend.SaleCommissionExtendService;
import com.ruoyi.common.base.biz.service.biz.BaseBizServiceImpl;
import com.ruoyi.common.utils.excl.model.ExcelCreateModel;
import com.ruoyi.common.utils.excl.utils.ExcelUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SaleCommissionBizServiceImpl
        extends BaseBizServiceImpl<SaleCommission, SaleCommissionReq, SaleCommissionRes, SaleCommissionDo, SaleCommissionPo, SaleCommissionService, SaleCommissionExtendService>
        implements SaleCommissionBizService {

    @Autowired
    private ConfBizService confBizService;

    @Autowired
    private SaleAccountService saleAccountService;

    @Autowired
    private SaleService saleService;

    /**
     * 订单生成之后，创建订单返利记录
     * @param orderPaySuccessEvent
     */
    @EventListener
    @Async
    public void save(OrderPaySuccessEvent orderPaySuccessEvent) {
        Order order = (Order) orderPaySuccessEvent.getSource();
        saveByOrder(order);
    }

    @EventListener
    public void recalculatePrice(RefundPayoutSuccessEvent refundPayoutSuccessEvent) {
        Order order = (Order) refundPayoutSuccessEvent.getSource();
        recalculatePrice(order.getId(), order.getFinalPrice());
    }

    @Override
    public void saveByOrder(Order order) {
        Sale sale = saleService.getById(order.getSaleId());
        CommissionRateRes commissionRateRes = confBizService.getConf(ConfConst.Code.COMMISSION_RATE);
        CommissionRate effective = commissionRateRes.getEffective();

        //保存本级返利记录
        BigDecimal thisLevelRate = effective.getThisLevelRate();
        SaleCommission thisLevel = newCommission(order,
                SaleCommissionConst.TypeCode.SIGN_UP,
                thisLevelRate,
                SaleCommissionConst.LevelCode.THIS_LEVEL,
                sale);
        BaseEntityUtil.fillCreateUser(thisLevel);
        this.getService().save(thisLevel);
        saleAccountService.addTotalPrice(sale.getId(), thisLevel.getPrice());

        //保存上级返利记录
//        if (ObjectUtil.isEmpty(parent)) {
//            return ;
//        }
        Sale parent = saleService.getById(sale.getParentId());
        if (SaleConst.TypeEnum.ROOT.getCode().equals(parent.getTypeCode())) {
            return ;
        }

        BigDecimal upOneLevelRate = effective.getUpOneLevelRate();
        SaleCommission upOne = newCommission(order,
                SaleCommissionConst.TypeCode.TAKE_FROM_CHILD,
                upOneLevelRate,
                SaleCommissionConst.LevelCode.UP_ONE_LEVEL,
                parent);
        BaseEntityUtil.fillCreateUser(upOne);
        this.getService().save(upOne);
        saleAccountService.addTotalPrice(parent.getId(), thisLevel.getPrice());
    }

    /**
     * 新建一条记录对象
     * @param order 订单对象
     * @param typeCode 佣金类型
     * @param rate 返佣比例
     * @param levelCode 返佣级别
     * @param sale 获利商家
     * @return 返回佣金记录对象
     */
    private SaleCommission newCommission(Order order,
                                         SaleCommissionConst.TypeCode typeCode,
                                         BigDecimal rate,
                                         SaleCommissionConst.LevelCode levelCode,
                                         Sale sale) {
        SaleCommission commission = SaleCommission.builder()
                .typeCode(typeCode.getCode())
                .orderPrice(order.getFinalPrice())
                .rate(rate)
                .levelCode(levelCode.getCode())
                .orderId(order.getId())
                .statusCode(SaleCommissionConst.StatusCode.FLOW.getCode())
                .saleId(sale.getId())
                .saleNum(sale.getNum())
                .saleName(sale.getName())
                .price(rate.multiply(order.getFinalPrice()).divide(new BigDecimal("100"), 0, BigDecimal.ROUND_DOWN))
                .build();
        return commission;
    }

    @Override
    public boolean recalculatePrice(Long orderId, BigDecimal orderPrice) {
        LambdaQueryWrapper<SaleCommission> queryWrapper = new LambdaQueryWrapper<SaleCommission>()
                .ge(SaleCommission::getOrderId, orderId)
                .eq(SaleCommission::getStatusCode, SaleCommissionConst.StatusCode.FLOW.getCode());
        List<SaleCommission> list = this.getService().list(queryWrapper);
        list.forEach(saleCommission -> {
            BigDecimal newPrice = saleCommission.getRate().divide(new BigDecimal("100")).multiply(orderPrice).setScale(0, BigDecimal.ROUND_DOWN);
            BigDecimal diffPrice = saleCommission.getPrice().subtract(newPrice);
            saleAccountService.subTotalPrice(saleCommission.getSaleId(), diffPrice);
            saleCommission.setRefundPrice(saleCommission.getRefundPrice().add(saleCommission.getOrderPrice().subtract(orderPrice)));
            saleCommission.setOrderPrice(orderPrice);
            saleCommission.setPrice(newPrice);
            saleCommission.setUpdateBy(saleCommission.getSaleId());
        });
        return this.getService().updateBatchById(list);
    }

    @Override
    public Workbook createExportWorkbook(SaleCommissionReq saleCommissionReq) {
        List<SaleCommissionPo> saleCommissionPoList = this.getService().listPoByDo(saleCommissionReq);
        String suffix = "";
        if (ObjectUtil.isNotEmpty(saleCommissionReq.getPayDateStart()) && ObjectUtil.isNotEmpty(saleCommissionReq.getPayDateEnd())) {
            suffix = " 支付日期：" + DateUtil.format(saleCommissionReq.getPayDateStart(), "yyyy-MM-dd") + " - " + DateUtil.format(saleCommissionReq.getPayDateEnd(), "yyyy-MM-dd");
        }
        Workbook template = ExcelUtils.createExcelWorkbookSheetNumber(new ExcelCreateModel(
                SaleCommissionConst.EXPORT_EXCEL_TITLE,
                SaleCommissionConst.EXPORT_EXCEL_TITLE + suffix,
                saleCommissionPoList,
                SaleCommissionPo.class));
        return template;
    }

    @Override
    public boolean updateStatusCodeAndAddBalance() {
        SaleCommissionReq saleCommissionReq = new SaleCommissionReq();
        saleCommissionReq.setStatusCode(SaleCommissionConst.StatusCode.FLOW.getCode());
        saleCommissionReq.setNeRefundStatusCode(OrderRefundConst.StatusEnum.REFUNDING.getCode());
        saleCommissionReq.setPayTimeEnd(DateUtil.offsetDay(new Date(), -1));
        List<SaleCommissionPo> saleCommissionPoList = this.getService().listPoByDo(saleCommissionReq);
        if (ObjectUtil.isEmpty(saleCommissionPoList)) {
            return true;
        }
        List<Long> saleCommissionIdList = saleCommissionPoList.stream().map(SaleCommissionPo::getId).collect(Collectors.toList());
        this.getService().updateStatusBatchByIdList(saleCommissionIdList, SaleCommissionConst.StatusCode.FIXED);
        return saleAccountService.addBalanceByCommissionBatch(saleCommissionPoList);
    }

    /**
     * 更新佣金状态标记，如果变为fixed则保存返佣金额至账户余额
     */
    @EventListener
    public void updateStatusCodeAndAddBalance(EveryTenMinutesEvent everyTenMinutesEvent) {
        List<String> taskList = (List) everyTenMinutesEvent.getSource();
        if (taskList.contains("updateStatusCodeAndAddBalance") == false) {
            return ;
        }
        updateStatusCodeAndAddBalance();
    }

}
